#include "stdafx.h"
#include "tools.h"
#include <assert.h>

// Do not assert in this function since it is used by the asssertion code!
std::wstring SysMultiByteToWide(const std::string& mb, unsigned int code_page) {
    if (mb.empty())
        return std::wstring();

    int mb_length = static_cast<int>(mb.length());
    // Compute the length of the buffer.
    int charcount = MultiByteToWideChar(code_page, 0,
        mb.data(), mb_length, NULL, 0);
    if (charcount == 0)
        return std::wstring();

    std::wstring wide;
    wide.resize(charcount);
    MultiByteToWideChar(code_page, 0, mb.data(), mb_length, &wide[0], charcount);

    return wide;
}

// Do not assert in this function since it is used by the asssertion code!
std::string SysWideToMultiByte(const std::wstring& wide, unsigned int code_page) {
    int wide_length = static_cast<int>(wide.length());
    if (wide_length == 0)
        return std::string();

    // Compute the length of the buffer we'll need.
    int charcount = WideCharToMultiByte(code_page, 0, wide.data(), wide_length,
        NULL, 0, NULL, NULL);
    if (charcount == 0)
        return std::string();

    std::string mb;
    mb.resize(charcount);
    WideCharToMultiByte(code_page, 0, wide.data(), wide_length,
        &mb[0], charcount, NULL, NULL);

    return mb;
}

void SetThreadName(DWORD tid, char* tname)
{
#pragma pack(push,8)
    typedef struct tagTHREADNAME_INFO
    {
        DWORD dwType; // Must be 0x1000.
        LPCSTR szName; // Pointer to name (in user addr space).
        DWORD dwThreadID; // Thread ID (-1=caller thread).
        DWORD dwFlags; // Reserved for future use, must be zero.
    } THREADNAME_INFO;
#pragma pack(pop)

    const DWORD MS_VC_EXCEPTION = 0x406D1388;

    THREADNAME_INFO info;
    info.dwType = 0x1000;
    info.szName = tname;
    info.dwThreadID = tid;
    info.dwFlags = 0;

    __try
    {
        RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
    }
}